﻿@page "/signal"

@inject IRecipesService RecipeService
@inject IResizeService  ResizeService

@implements IDisposable

<h1>Signal Plot</h1>

<div class="my-4">
    <div class="fs-5">Number of data points:</div>
    <button type="button" class="btn btn-primary" @onclick="()=>SetupPlots(1_000, true)">1k</button>
    <button type="button" class="btn btn-primary" @onclick="()=>SetupPlots(10_000, true)">10k</button>
    <button type="button" class="btn btn-primary" @onclick="()=>SetupPlots(100_000, true)">100k</button>
    <button type="button" class="btn btn-primary" @onclick="()=>SetupPlots(1_000_000, true)">1M</button>
</div>

@if (RecipeService.ShowOpenGL)
{
    <BlazorPlotGL @ref=BlazorPlotGL Style="@plotSize" />
}
else
{
    <BlazorPlot @ref=BlazorPlot Style="@plotSize" />
}

@code {
    BlazorPlot BlazorPlot { get; set; } = new();
    BlazorPlotGL BlazorPlotGL { get; set; } = new();

    ScottPlot.Plottables.Signal? lastRenderedSignal = null;
    string plotSize = "width: min(100%, 800px); height: 600px;";
    int lastCount = 10_000;
    protected override void OnAfterRender(bool firstRender)
    {
        if (firstRender)
        {
            SetupPlots(lastCount, true);
        }

        base.OnAfterRender(firstRender);
    }
    protected override void OnInitialized()
    {
        RecipeService.BackendChanged += this.RefreshWithPlot;
        ResizeService.ResizeAction += this.ResizePlot;
        plotSize = $"width: min(100%, {ResizeService.PixelWidth:F0}px); height: 600px;";
    }

    public void Dispose()
    {
        RecipeService.BackendChanged -= this.RefreshWithPlot;
        ResizeService.ResizeAction -= this.ResizePlot;
    }
    private void RefreshWithPlot()
    {
        StateHasChanged();
        InvokeAsync(async () =>
        {
            // add little delay to ensure BlazorPlot is visible to ensure refresh works!
            await Task.Delay(1);
            SetupPlots(lastCount, false);
        });
    }
    private void SetupPlots(int count, bool reset)
    {
        if (reset || lastCount != count)
            lastRenderedSignal = null;
        lastCount = count;
        lastRenderedSignal ??= new(new ScottPlot.DataSources.SignalSourceDouble(ScottPlot.Generate.RandomWalk(count), 1))
        {
            Color = Colors.Blue
        };
        if (RecipeService.ShowOpenGL)
        {
            BlazorPlotGL.Plot.Clear();
            BlazorPlotGL.Plot.Title($"Signal with {count:N0} points (OpenGL)");
            BlazorPlotGL.Plot.PlottableList.Add(lastRenderedSignal);
            BlazorPlotGL.Plot.Axes.AutoScale();
            BlazorPlotGL.Refresh();
        }
        else
        {
            BlazorPlot.Plot.Clear();
            BlazorPlot.Plot.Title($"Signal with {count:N0} points");
            BlazorPlot.Plot.PlottableList.Add(lastRenderedSignal);
            BlazorPlot.Plot.Axes.AutoScale();
            BlazorPlot.Refresh();
        }
    }
    protected void ResizePlot(System.Drawing.SizeF newSize)
    {
        plotSize = $"width: min(100%, {newSize.Width:F0}px); height: 600px;";
        RefreshWithPlot();
    }
}